// Package transaction : 分布式事务模块
// 尝试实现基于 Percolator 的分布式事务，并向外提供服务
package transaction

import (
	"database/sql"
	"fmt"
	"sync"
	"time"
)

// Transaction 表示一个分布式事务
type Transaction struct {
	ID        string
	TxMap     map[string]*sql.Tx
	TxMapLock sync.Mutex
}

// BeginTransaction 开始一个新的分布式事务
func BeginTransaction() *Transaction {
	return &Transaction{
		ID:        fmt.Sprintf("tx-%d", time.Now().UnixNano()),
		TxMap:     make(map[string]*sql.Tx),
		TxMapLock: sync.Mutex{},
	}
}

// Commit 提交事务
func (t *Transaction) Commit() error {
	t.TxMapLock.Lock()
	defer t.TxMapLock.Unlock()

	var wg sync.WaitGroup
	errChan := make(chan error, len(t.TxMap))

	// 并行处理
	for key, tx := range t.TxMap {
		wg.Add(1)
		go func(k string, tx *sql.Tx) {
			defer wg.Done()
			if err := tx.Commit(); err != nil {
				errChan <- fmt.Errorf("failed to commit transaction %s on %s: %v", t.ID, k, err)
			}
		}(key, tx)
	}

	wg.Wait()
	close(errChan)

	// 检查错误
	for err := range errChan {
		return err
	}

	// 删除操作在锁内完成
	for key := range t.TxMap {
		delete(t.TxMap, key)
	}
	return nil
}

// RollBack 回滚事务
func (t *Transaction) RollBack() error {
	t.TxMapLock.Lock()
	defer t.TxMapLock.Unlock()

	var wg sync.WaitGroup
	errChan := make(chan error, len(t.TxMap))

	for key, tx := range t.TxMap {
		wg.Add(1)
		go func(k string, tx *sql.Tx) {
			defer wg.Done()
			if err := tx.Rollback(); err != nil {
				errChan <- fmt.Errorf("failed to rollback transaction %s on %s: %v", t.ID, k, err)
			}
			delete(t.TxMap, k)
		}(key, tx)
	}

	wg.Wait()
	close(errChan)

	// 检查错误
	for err := range errChan {
		return err
	}
	return nil
}
